package com.sparrow.source.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sparrow.source.common.dto.AccountQueryDTO;
import com.sparrow.source.common.dto.PassWordUpdate;
import com.sparrow.source.common.dto.RegistryDTO;
import com.sparrow.source.common.dto.Result;
import com.sparrow.source.common.enums.ResultEnum;
import com.sparrow.source.common.utils.RedisUtils;
import com.sparrow.source.persistense.IasAccount;
import com.sparrow.source.persistense.mapper.IasAccountMapper;
import com.sparrow.source.service.IasAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

import static com.sparrow.source.common.CommonConstant.DEFAULT_PASSWORD;
import static com.sparrow.source.common.CommonConstant.USER_ACCESS_KEY;

/**
 * @author bryceyung
 * @since 2024/12/5
 */
@Slf4j
@Service
public class IasAccountServiceImpl extends ServiceImpl<IasAccountMapper, IasAccount> implements IasAccountService {

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public Result login(String userName, String password) {
        // 用户名/密码校验
        if (StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("错误的用户名或密码");
        }
        // 账号是否存在以及状态是否启用校验
        IasAccount account = this.lambdaQuery().eq(IasAccount::getUserName, userName).eq(IasAccount::getStatus, 1)
                .eq(IasAccount::getDeleted, 0).one();

        if (account == null) {
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("未查询到用户信息，错误的用户名或密码");
        }

        // 密码加密之后校验
        String ms = DigestUtils.md5DigestAsHex((USER_ACCESS_KEY + password).getBytes());
        if (!ms.equals(account.getPassword())) {
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("密码错误");
        }
        String token = tokenGenerate(account);
        account.setToken(token);
        //        redisUtils.deleteUserToken(userStore, true, true);
        redisUtils.set(token, JSONObject.toJSONString(account), 30 * 60 * 60);
        return Result.build(ResultEnum.SUCCESS).setObject(account);
    }

    @Override
    public Result registry(RegistryDTO registryDTO, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token == null) {
            log.error("Account Registry error,no token found:[{}]", registryDTO.getUserName());
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("无权限,请重新登陆");
        }
        //        非管理员不可新增用户
        IasAccount mainAccount = JSONObject.parseObject(redisUtils.getObject(token).toString(), IasAccount.class);
        if (mainAccount.getType() != 1) {
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("无权限,请联系管理员进行操作");
        }
        IasAccount account = new IasAccount();
        account.setUserName(registryDTO.getUserName());
        account.setType(registryDTO.getType());
        account.setStatus(registryDTO.getStatus());
        account.setCreateTime(new Date());
        account.setPassword(DigestUtils.md5DigestAsHex((USER_ACCESS_KEY + DEFAULT_PASSWORD).getBytes()));
        return Result.build(ResultEnum.SUCCESS).setObject(baseMapper.insert(account));
    }

    @Override
    public Result passwordUpdate(PassWordUpdate passWordUpdate, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token == null) {
            log.error("Account Password Update error,no token found:[{}]", passWordUpdate.getAccountId());
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("无权限,请重新登陆");
        }
        IasAccount account = this.baseMapper.selectById(passWordUpdate.getAccountId());
        if (account == null) {
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("未查询到用户信息");
        }
        //旧密码校验
        if (!account.getFirstLogin()) {
            String ms = DigestUtils.md5DigestAsHex((USER_ACCESS_KEY + passWordUpdate.getOldPassword()).getBytes());
            if (!ms.equals(account.getPassword())) {
                return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("旧密码认证错误");
            }
        }
        redisUtils.deleteKey(token);
        account.setPassword(DigestUtils.md5DigestAsHex((USER_ACCESS_KEY + passWordUpdate.getNewPassword()).getBytes()));
        account.setFirstLogin(false);
        account.setUpdateTime(new Date());
        return Result.build(ResultEnum.SUCCESS).setObject(baseMapper.updateById(account));
    }

    @Override
    public Result logout(Integer accountId, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token == null) {
            log.error("Account logout Update error,no token found:[{}]", accountId);
            return Result.build(ResultEnum.PRECONDITION_FAILED).setMessage("无权限,请重新登陆");
        }
        redisUtils.deleteKey(token);
        return Result.build(ResultEnum.SUCCESS).setObject(true);
    }

    @Override
    public Result checkUserName(String userName) {
        return Result.build(ResultEnum.SUCCESS).setObject(lambdaQuery().eq(IasAccount::getUserName, userName).one()
                == null ? false : true);
    }

    @Override
    public Result queryAccount(Page<IasAccount> accountPage, AccountQueryDTO accountQueryDTO) {
        return Result.build(ResultEnum.SUCCESS).setObject(baseMapper.selectWithPage(accountQueryDTO.getUserName(), accountQueryDTO.getType(), accountQueryDTO.getStatus(), accountPage));
    }

    @Override
    public Result deleteAccount(Integer accountId) {
        IasAccount account = baseMapper.selectById(accountId);
        if (account == null) {
            return Result.build(ResultEnum.SUCCESS).setObject(false).setMessage("未查询到账号信息");
        }
        account.setDeleted(true);
        account.setUpdateTime(new Date());
        return Result.build(ResultEnum.SUCCESS).setObject(this.updateById(account));
    }

    @Override
    public Result updateStatusOrType(Integer accountId, Integer status, Integer type) {
        IasAccount account = baseMapper.selectById(accountId);
        if (account == null) {
            return Result.build(ResultEnum.SUCCESS).setObject(false).setMessage("未查询到账号信息");
        }
        if (status != null) {
            account.setStatus(status);
        }
        if (type != null) {
            account.setType(type);
        }
        return Result.build(ResultEnum.SUCCESS).setObject(this.updateById(account));
    }

    private String tokenGenerate(IasAccount account) {
        Date now = new Date();
        return JWT.create().withAudience(account.getId().toString(), account.getUserName(), String.valueOf(now.getTime()))
                .withIssuedAt(now)
                .sign(Algorithm.HMAC256(account.getPassword()));
    }
}
